﻿/*
Copyright © 2010 SectorPoint, Inc.

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Linq;
using System.Text;

namespace SectorPoint.Net.Mail
{
	/// <summary>
	/// Represents an email message retrieved using the SectorPoint.Net.Mail.Pop3Client class.
	/// </summary>
	public class Pop3Message
	{
		#region Constructor
		internal Pop3Message( int messageNumber, int messageSize, Pop3Client client )
		{
			this.MessageNumber = messageNumber;
			this.MessageSize = messageSize;
			this.client = client;
			this.retrieved = false;
			b_body = null;
			b_headers = null;
		}
		#endregion

		#region Public Methods
		public override string ToString()
		{
			return Body;
		}

		/// <summary>
		/// Marks this message for deletion.
		/// </summary>
		public void Delete()
		{
			client.DeleteMessage( MessageNumber );
		}
		#endregion

		#region Private Fields
		Pop3Client client;
		bool retrieved = false;
		#endregion

		#region Public Properties
		#region Backing Fields
		string b_body;
		NameValueCollection b_headers;
		#endregion
		/// <summary>
		/// Message number as returned in a scan listing by the POP3 server. TODO: This is not really useful, consider making internal.
		/// </summary>
		public int MessageNumber { get; private set; }

		/// <summary>
		/// Size of the message (including headers) in octets.
		/// </summary>
		public int MessageSize { get; private set; }

		/// <summary>
		/// Gets the body of the message.
		/// </summary>
		public string Body
		{
			get
			{
				EnsureRetrieval();
				return b_body;
			}
		}

		/// <summary>
		/// Gets a System.Collections.Specialized.NameValueCollection that contains the message headers.
		/// </summary>
		public NameValueCollection Headers
		{
			get
			{
				EnsureRetrieval();
				return b_headers;
			}
		}
		#endregion

		#region Private Methods
		/// <summary>
		/// Ensures that this message has been retrieved from the POP3 server.
		/// </summary>
		void EnsureRetrieval()
		{
			if (this.retrieved)
				return;

			client.SendCommand( Pop3Command.Retrieve, MessageNumber.ToString( System.Globalization.CultureInfo.InvariantCulture ) );
			byte[] message = client.Read();

			int messageOffset = 0;
			int messageLength = message.Length;
			b_headers = new NameValueCollection();

			for (int i = 0; i < message.Length; i++)
			{
				if (message[i] == 0xD)		// only should happen when we encounter \r\n\r
				{
					messageOffset = i + 1;
					break;
				}

				StringBuilder newLine = new StringBuilder( 30 );

				while (message[i] != 0xD && i < messageLength)
				{
					newLine.Append( (char)message[i] );
					i++;
				}
				i++;	// account for the \n

				string currentLine = newLine.ToString();
				int separatorLocation = currentLine.IndexOf( ':' );
				if (separatorLocation > 0)
				{
					string key = currentLine.Substring( 0, separatorLocation );
					string value = currentLine.Substring( separatorLocation + 2 );

					b_headers.Add( key, value );
				}
			}

			ASCIIEncoding asc = new ASCIIEncoding();
			b_body = asc.GetString( message, messageOffset, messageLength - messageOffset );

			this.retrieved = true;
		}
		#endregion
	}
}
